from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import datetime
from abc import ABC,abstractmethod

class KeyboardOperationBase(ABC):
    def __init__(self):
        pass

    def only_clear(self):
        self.element.send_keys(Keys.BACKSPACE * 100)

    def only_input(self,InputValue):
        self.element.send_keys(InputValue)
    
    def check_clear(self,attribute:str = "value", timeout=5):
        start_time = datetime.datetime.now()
        while datetime.datetime.now() - datetime.timedelta(seconds=timeout) < start_time:

            # end condition
            attributeValue = self.element.get_attribute(name=attribute)
            if attributeValue == "" or attributeValue is None:
                return True

            # clear operation
            self.element.send_keys(Keys.BACKSPACE*20)
        return False

    def check_input(self,InputValue:str,attribute:str = "value"):
        if self.element.get_attribute(name=attribute) == InputValue:
            return True
        else:
            self.element.send_keys(InputValue)
            if self.element.get_attribute(name=attribute) == InputValue:
                return True
            else:
                return False

    def fast_input(self,InputValue):
        self.only_clear()
        self.only_input(InputValue=InputValue)
    
    def safe_clear(self, attribute: str = None, timeout=5) -> bool:
        if attribute is None:
            self.only_clear()
            return True
        else:
            self.check_clear(attribute=attribute,timeout=timeout)
            return True

    def safe_input(self, InputValue: str, attribute: str = None, timeout=5) -> bool:
        if attribute is None:
            self.only_clear()
            self.only_input(InputValue=InputValue)
            return True
        else:
            self.check_clear(attribute=attribute,timeout=timeout)
            self.check_input(InputValue=InputValue,attribute=attribute)
            return True
    
    def condition_clean(self,condition_xpath:str,timeout=5) -> bool:
        self.only_clear()
        _et = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
        while datetime.datetime.now() < _et:
            try:
                self.driver.find_element(By.XPATH,condition_xpath)
                return True
            except:
                continue
        return False

    def condition_input(self,InputValue:str,condition_xpath:str,timeout=5,expect_exists=True) -> bool:
        self.only_clear()
        self.only_input(InputValue=InputValue)
        _et = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
        while datetime.datetime.now() < _et:
            try:
                self.driver.find_element(By.XPATH,condition_xpath)
                if expect_exists:
                    return True
            except:
                if not expect_exists:
                    return True
                continue
        return False

    @property
    @abstractmethod
    def element() -> WebElement:
        pass
    
    @property
    @abstractmethod
    def driver() -> WebDriver:
        pass